package com.baor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baor.dao.*;
import com.baor.domain.*;
import com.baor.enums.FuncEnum;
import com.baor.service.DistributionOrderService;
import com.baor.utils.AjaxResult;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DistributionOrderServiceImpl implements DistributionOrderService {


    @Autowired
    private DistributionRecordDao recordDao;

    @Autowired
    private MoneyDao moneyDao;

    @Autowired
    private VipDao userDao;

    @Autowired
    private ExamineDao eDao;

    @Autowired
    private DistributorDao dDao;

    @Autowired
    private ProxyDao pDao;


    private Page<DistributionRecordVo> getPage(Map<String,Object> map){
        if ( map.get("pageIndex") == null || "".equals(map.get("pageIndex")) )
            map.put("pageIndex",1);
        if ( map.get("pageSize") == null || "".equals(map.get("pageSize")) )
            map.put("pageSize",10);
        Long pageIndex = Long.valueOf(map.get("pageIndex").toString());
        Long pageSize = Long.valueOf(map.get("pageSize").toString());
        return new Page<>(pageIndex,pageSize);
    }


    private MPJLambdaWrapper<DistributionRecordVo> getMpj(){
        MPJLambdaWrapper<DistributionRecordVo> mpj = new MPJLambdaWrapper<>();
        mpj
                .selectAll(DistributionRecordVo.class)//不需要第二行的话,第一行一同删除,用这行代替
                .selectAs(UserVo::getUserName,OrderVo::getUserId)
                .leftJoin(UserVo.class,UserVo::getUserId,DistributionRecordVo::getUserId)
                .selectAs(GoodsVo::getGoodsName,DistributionRecordVo::getGoodsId)
                .selectAs(GoodsVo::getGoodsImage,DistributionRecordVo::getGoodsImage)
                .leftJoin(GoodsVo.class,GoodsVo::getGoodsId,DistributionRecordVo::getGoodsId)
                .selectFunc(FuncEnum.IF_LEVEL,DistributionRecordVo::getDistributionLevel)
                .selectFunc(FuncEnum.IF_DISSTATUS,DistributionRecordVo::getDistributionStatus);
        return mpj;
    }

    @Override
    public AjaxResult<?> list(Map<String, Object> map) {
        MPJLambdaWrapper<DistributionRecordVo> mpj = getMpj()
                .eq(DistributionRecordVo::getSiteId,map.get("siteId"));
        if ( map.get("status") != null && !"".equals(map.get("status")) )
            mpj.eq(DistributionRecordVo::getDistributionStatus,map.get("status"));
        if ( map.get("startTime") != null && ! "".equals(map.get("startTime")) )//>
            mpj.ge(DistributionRecordVo::getCreateTime,map.get("startTime"));//ge >=
        if ( map.get("endTime") != null && ! "".equals(map.get("endTime")) )//<
            mpj.le(DistributionRecordVo::getCreateTime,map.get("endTime"));//le <=
        if ( map.get("userId") != null && !"".equals(map.get("userId")) ){
            mpj.eq(DistributionRecordVo::getUserId,map.get("userId"));
        }
        Page<DistributionRecordVo> page = recordDao.selectPage(getPage(map),mpj);
        //-------- 结果处理 --------
        List<DistributionRecordVo> records = page.getRecords();
//        records.stream().
        long pages = page.getPages();
        //-------- 数据封装 --------
        Map<String,Object> res = new HashMap<>();
        res.put("pageCount",pages);
        res.put("list",records);
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult<?> moneyList(Map<String, Object> map) {
        MPJLambdaWrapper<MoneyVo> mpj = getMpj2()
                .eq(MoneyVo::getSiteId, map.get("siteId"))
                .in(MoneyVo::getMoneyStatus,0,1,2);
        if ( map.get("startTime") != null && ! "".equals(map.get("startTime")) )//>
            mpj.ge(MoneyVo::getCreateTime,map.get("startTime"));//ge >=
        if ( map.get("endTime") != null && ! "".equals(map.get("endTime")) )//<
            mpj.le(MoneyVo::getCreateTime,map.get("endTime"));//le <=
        if ( map.get("source") != null && ! "".equals(map.get("source")) )
            mpj.like(MoneyVo::getMoneySourceId,map.get("source"));
        /**
         * 因为使用 or ，所以所有的可能不存在的参数需要重新匹配一遍
         * 这样 or 的第二个条件才会有这些条件限制
         */
        if ( map.get("userName") != null && ! "".equals(map.get("userName")) ){
            List<UserVo> list = userDao.selectList(new LambdaQueryWrapper<UserVo>()
                    .like(UserVo::getUserAccount, map.get("userName"))
                    .or(x -> x
                            .like(UserVo::getUserTel, map.get("userName")))
                    .or(y -> y
                            .like(UserVo::getUserName, map.get("userName"))));
            if ( list.size() > 0 )
                mpj.in(MoneyVo::getUserId,list.stream()
                        .map(x -> x.getUserId()).collect(Collectors.toList()));
            else
                mpj.eq(MoneyVo::getUserId,0);
        }
        Page<MoneyVo> page = moneyDao.selectPage(getPage2(map), mpj);
        List<MoneyVo> records = page.getRecords();
        long pages = page.getPages();
        //-------- 数据封装 --------
        Map<String,Object> res = getMap(map,false,0,1,2);
        res.put("pageCount",pages);
        res.put("list",records);
        return AjaxResult.success(res);
    }

    private Map<String,Object> getMap(Map<String,Object> map,boolean flag,Object ...args){
        Map<String,Object> res = new HashMap<>();
        MPJLambdaWrapper<MoneyVo> mpj = getMpj2()
                .eq(MoneyVo::getSiteId, map.get("siteId"))
                .in(MoneyVo::getMoneyStatus,args);
        if ( map.get("startTime") != null && ! "".equals(map.get("startTime")) )//>
            mpj.ge(MoneyVo::getCreateTime,map.get("startTime"));//ge >=
        if ( map.get("endTime") != null && ! "".equals(map.get("endTime")) )//<
            mpj.le(MoneyVo::getCreateTime,map.get("endTime"));//le <=
        if ( map.get("source") != null && ! "".equals(map.get("source")) )//<
            mpj.like(MoneyVo::getMoneySourceId,map.get("source"));//le <=
        List<MoneyVo> records = moneyDao.selectList(mpj);
        res.put("total_money",records.stream()
                .map(x -> x.getMoneyChange())
                .reduce(BigDecimal.ZERO,BigDecimal::add));//佣金总额
        res.put("not_money",records.stream().filter(x -> x.getMoneyStatus().equals("未提现"))
                .map(x -> x.getMoneyChange())
                .reduce(BigDecimal.ZERO,BigDecimal::add));//可提现
        res.put("in_money",records.stream().filter( x -> x.getMoneyStatus().equals("提现中"))
                .map(x -> x.getMoneyChange())
                .reduce(BigDecimal.ZERO,BigDecimal::add));//体现中
        res.put("had_money",records.stream().filter( x -> x.getMoneyStatus().equals("已提现"))
                .map(x -> x.getMoneyChange())
                .reduce(BigDecimal.ZERO,BigDecimal::add));//累计结算佣金
        if ( flag ){
            res.put("will_money",
                    records.stream().filter( x -> x.getMoneyStatus().equals("提现中"))
                            .map(x -> x.getMoneyChange())
                            .reduce(BigDecimal.ZERO,BigDecimal::add)
                            .add(
                                    records.stream().filter( x -> x.getMoneyStatus().equals("未提现"))
                                            .map(x -> x.getMoneyChange())
                                            .reduce(BigDecimal.ZERO,BigDecimal::add)));//待结算=未提现+提现中
            res.put("distribution_money",records.stream().filter( x -> x.getMoneySourceId().equals("佣金返现"))
                    .map(x -> x.getMoneyChange())
                    .reduce(BigDecimal.ZERO,BigDecimal::add));
            res.put("team_money",records.stream().filter( x -> x.getMoneySourceId().equals("团队分红"))
                    .map(x -> x.getMoneyChange())
                    .reduce(BigDecimal.ZERO,BigDecimal::add));
            res.put("task_money",records.stream().filter( x -> x.getMoneySourceId().equals("任务奖励"))
                    .map(x -> x.getMoneyChange())
                    .reduce(BigDecimal.ZERO,BigDecimal::add));
            res.put("proxy_money",records.stream().filter( x -> x.getMoneySourceId().equals("代理返现"))
                    .map(x -> x.getMoneyChange())
                    .reduce(BigDecimal.ZERO,BigDecimal::add));
            res.put("reward_money",records.stream().filter( x -> x.getMoneySourceId().equals("销售奖励"))
                    .map(x -> x.getMoneyChange())
                    .reduce(BigDecimal.ZERO,BigDecimal::add));
        }
        return res;
    }

    private Page<MoneyVo> getPage2(Map<String,Object> map){
        if ( map.get("pageIndex") == null || "".equals(map.get("pageIndex")) )
            map.put("pageIndex",1);
        if ( map.get("pageSize") == null || "".equals(map.get("pageSize")) )
            map.put("pageSize",10);
        Long pageIndex = Long.valueOf(map.get("pageIndex").toString());
        Long pageSize = Long.valueOf(map.get("pageSize").toString());
        return new Page<>(pageIndex,pageSize);
    }

    private MPJLambdaWrapper<MoneyVo> getMpj2(){
        MPJLambdaWrapper<MoneyVo> mpj =
                new MPJLambdaWrapper<MoneyVo>()
                        .selectAll(MoneyVo.class)
                        .selectAs(UserVo::getUserAccount,MoneyVo::getUserAccount)
                        .selectAs(UserVo::getUserImage,MoneyVo::getUserImage)
                        .selectAs(UserVo::getUserName,MoneyVo::getUserName)
                        .selectAs(UserVo::getUserTel,MoneyVo::getUserTel)
                        .leftJoin(UserVo.class,UserVo::getUserId,MoneyVo::getUserId)
                        .selectFunc(FuncEnum.CASE_MS,MoneyVo::getMoneyStatus);
        return mpj;
    }

    @Override
    public AjaxResult<?> yue(Map<String, Object> map) {
        MPJLambdaWrapper<MoneyVo> mpj = getMpj2()
                .eq(MoneyVo::getSiteId, map.get("siteId"));
        if ( map.get("startTime") != null && ! "".equals(map.get("startTime")) )//>
            mpj.ge(MoneyVo::getCreateTime,map.get("startTime"));//ge >=
        if ( map.get("endTime") != null && ! "".equals(map.get("endTime")) )//<
            mpj.le(MoneyVo::getCreateTime,map.get("endTime"));//le <=
        if ( map.get("source") != null && ! "".equals(map.get("source")) )
            mpj.like(MoneyVo::getMoneySourceId,map.get("source"));
        if ( map.get("type") != null && ! "".equals(map.get("type")) )
            mpj.like(MoneyVo::getAccountType,map.get("type"));
        if ( map.get("userName") != null && ! "".equals(map.get("userName")) ){
            List<UserVo> list = userDao.selectList(new LambdaQueryWrapper<UserVo>()
                    .like(UserVo::getUserAccount, map.get("userName"))
                    .or(x -> x
                            .like(UserVo::getUserTel, map.get("userName")))
                    .or(y -> y
                            .like(UserVo::getUserName, map.get("userName"))));
            if ( list.size() > 0 )
                mpj.in(UserVo::getUserId,list.stream().map(x -> x.getUserId()).collect(Collectors.toList()));
            else
                mpj.eq(UserVo::getUserId,0);
        }
        Page<MoneyVo> page = moneyDao.selectPage(getPage2(map), mpj);
        List<MoneyVo> records = page.getRecords();
        long pages = page.getPages();
        LambdaQueryWrapper<UserVo> select = new LambdaQueryWrapper<UserVo>()
                .select(UserVo::getUserId)
                .select(UserVo.class,x -> x.getColumn().equals("user_canuse_money")
                        || x.getColumn().equals("user_can_be")
                        || x.getColumn().equals("user_cant_be"))
                .eq(UserVo::getSiteId,map.get("siteId"));
        if ( map.get("userId") != null && ! "".equals(map.get("userId")) )
            select.like(UserVo::getUserId,map.get("userId"));
                // select 补充逻辑
                if ( map.get("userName") != null && ! "".equals(map.get("userName")) ){
                    List<UserVo> list = userDao.selectList(new LambdaQueryWrapper<UserVo>()
                            .like(UserVo::getUserAccount, map.get("userName"))
                            .or(x -> x
                                    .like(UserVo::getUserTel, map.get("userName")))
                            .or(y -> y
                                    .like(UserVo::getUserName, map.get("userName"))));
                    if ( list.size() > 0 )
                        select.in(UserVo::getUserId,list.stream().map(x -> x.getUserId()).collect(Collectors.toList()));
                    else
                        select.eq(UserVo::getUserId,0);
                }
        List<UserVo> list = userDao.selectList(select);
        //-------- 数据封装 --------
        Map<String,Object> res = new HashMap<>();
        res.put("total_money",list.stream()
                .map(x -> x.getUserCanuseMoney())
                .reduce(BigDecimal.ZERO,BigDecimal::add));
        res.put("can_be",list.stream()
                .map(x -> x.getUserCanBe())
                .reduce(BigDecimal.ZERO,BigDecimal::add));
        res.put("cant_be",list.stream()
                .map(x -> x.getUserCantBe())
                .reduce(BigDecimal.ZERO,BigDecimal::add));
        res.put("pageCount",pages);
        res.put("list",records);
        return AjaxResult.success(res);

    }

    @Override
    public AjaxResult<?> disTotal(Map<String, Object> map) {
        Map<String,Object> res = getMap(map,true,0,1,2,3,4,5);
        res.put("count_examine",eDao.selectCount(new LambdaQueryWrapper<ExamineVo>()
                .eq(ExamineVo::getSiteId,map.get("siteId"))));
        res.put("count_distributor",dDao.selectCount(new LambdaQueryWrapper<DistributorVo>()
                .eq(DistributorVo::getSiteId,map.get("siteId"))));
        res.put("count_proxy",pDao.selectCount(new LambdaQueryWrapper<ProxyVo>()
                .eq(ProxyVo::getSiteId,map.get("siteId"))));
        return AjaxResult.success(res);
    }


//    private MPJLambdaWrapper<MoneyVo> getMpj2(){
//        MPJLambdaWrapper<MoneyVo> mpj = JoinWrappers.lambda(MoneyVo.class)
//                .selectAll(MoneyVo.class)
//                .selectSub(MoneyVo.class,x -> x
//                        .select(UserVo::getUserName)
//                        .eq(MoneyVo::getMoneyId,UserVo::getUserId),
//        MoneyVo::getMoneyId);
//        return mpj;
//    }

//    SELECT (
//            SELECT st.id FROM `user` st WHERE (st.id = t.id) limit 1 ) AS id FROM `user` t
//        LEFT JOIN address t1 ON (t1.user_id = t.id)
//    WHERE t1.del=false AND (t.id <= ?)


}
